var GEW_VERSION = "0.4.0";
// Gew Flag
var DEBUG_DRAW = true;
var WEBGL_DEBUG = false; // Eable this flag to use debug webgl context ( check GL error after every GL call )

var activeGame;
/*
 * Event is only tested on FF& chrome
 * 
 */
function stopDefautEventFlow(e)
{
  if( e.preventDefault ) 
    e.preventDefault();
  else
    e.returnValue = false;
  if( e.stopPropagation )
    e.stopPropagation(); 
  else
    e.cancelBubble = true;
}
// Calculate mouse_x and mouse_y relative with canvas
function calcCanvasXY(e,canvas)
{
  if (e.offsetX && e.offsetY) // Chrome 
  {
    e.canvasX = e.offsetX;
    e.canvasY = e.offsetY;
  }
  else // Firefox 
  {
    e.canvasX = e.pageX - canvas.offsetLeft;
    e.canvasY = e.pageY - canvas.offsetTop;
  }
}
function onMouseUp(e)
{
  calcCanvasXY(e,this);
  activeGame.screens[activeGame.activeScreen].onMouseUp(e);
  //stopDefautEventFlow(e);
}
function onMouseDown(e)
{
  calcCanvasXY(e,this);
  activeGame.screens[activeGame.activeScreen].onMouseDown(e);
  //stopDefautEventFlow(e);
}
function onMouseMove(e)
{
  calcCanvasXY(e,this);
  activeGame.screens[activeGame.activeScreen].onMouseMove(e);
  //stopDefautEventFlow(e);
}
// Only run on Chrome now!
function onMouseWheel(e)
{
  calcCanvasXY(e,this);
  var delta = (e.wheelDelta) ? e.wheelDelta : e.detail;
  e.delta = delta;
  activeGame.screens[activeGame.activeScreen].onMouseWheel(e);
  //stopDefautEventFlow(e);
}
function onMouseOver(e)
{
  activeGame.isMouseIn = true;
  //stopDefautEventFlow(e);
}
function onMouseOut(e)
{
  activeGame.isMouseIn = false;
  //stopDefautEventFlow(e);
}

function onKeyUp(e)
{
  if(!activeGame.isMouseIn)
    return;
  if (window.event) { // IE
    e.keynum = e.keyCode;
  } else if (e.which) { // Netscape/Firefox/Opera
    e.keynum = e.which;
  }
  e.keychar = String.fromCharCode(e.keynum);
  
  activeGame.screens[activeGame.activeScreen].onKeyUp(e);
  //stopDefautEventFlow(e);
}
function onKeyDown(e)
{
  if(!activeGame.isMouseIn)
    return;
  if (window.event) { // IE
    e.keynum = e.keyCode;
  } else if (e.which) { // Netscape/Firefox/Opera
    e.keynum = e.which;
  }
  e.keychar = String.fromCharCode(e.keynum);
  
  activeGame.screens[activeGame.activeScreen].onKeyDown(e);
  //stopDefautEventFlow(e);
}
function onKeyPress(e)
{
  if(!activeGame.isMouseIn)
    return;
  if (window.event) { // IE
    e.keynum = e.keyCode;
  } else if (e.which) { // Netscape/Firefox/Opera
    e.keynum = e.which;
  }
  e.keychar = String.fromCharCode(e.keynum);
  activeGame.screens[activeGame.activeScreen].onKeyPress(e);
  //stopDefautEventFlow(e);
}

function gewGame(canvas_id)
{
  var canvas = document.getElementById(canvas_id);
  this.canvas = canvas;
  this.isMouseIn = true;
  var gl;
  
  var attribute =  {alpha:true,
                    depth:true,
                    stencil:true,
                    antialias:true,
                    premultipliedAlpha:false};
  try
  {
    if (!WEBGL_DEBUG) 
      gl = canvas.getContext("webkit-3d",attribute);
    else 
    {
      gl = WebGLDebugUtils.makeDebugContext(canvas.getContext("webkit-3d"));
    }
  }
  catch(e)
  {
  }
  if (!gl)
  {
    if (!WEBGL_DEBUG) 
      gl = canvas.getContext("experimental-webgl",attribute);
    else 
    {
      gl = WebGLDebugUtils.makeDebugContext(canvas.getContext("experimental-webgl",attribute));
    }
  }
  var attribs = gl.getContextAttributes();
  console.log(attribs);
  //gl.sampleCoverage(0.5,false);
  //gl.enable(gl.SAMPLE_COVERAGE);
  //gl.enable(gl.SAMPLE_ALPHA_TO_COVERAGE);
  gl.hint(gl.GENERATE_MIPMAP_HINT,gl.NICEST);
  gl.depthFunc(gl.LEQUAL);
  //gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL,true);
  //gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL,true);
  this.gl = gl;
  this.width = canvas.width;
  this.height = canvas.height;
  gl.viewport(0, 0, this.width, this.height);
  gl.clearColor (1.,1.,1.0,1.0); // Must set clear color to (1,1,1,1) because we use color channel for shadow mapping
  this.screens = [];
  this.previousScreen = -1;
  this.activeScreen = -1;
  this.firstRun = true;
  this.time = 0;
  this.startTime = 0;
  this.resourceManager = new gewResourceManager(this);
  this.textureManager = this.resourceManager.textureManager;
  this.meshManager = this.resourceManager.meshManager;
  
  // Create default obj idx buffer ( that contain only 0 )
  var defaultObjIdx = new WebGLFloatArray(GEW_MATH_MAX_USHORT);
  this.defaultObjIdxGLBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, this.defaultObjIdxGLBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, defaultObjIdx, gl.STATIC_DRAW);  
    
  if(!this.gl)
  {
    // failed to get the context
    alert("Game:contructor(): Can't get webgl context!");
    return false;
  }
  this.addScreen = function(screen,name)
  {
    if( this.screens[ name ] )
    {
      alert("Game:addScreen(): Warning - already have screen at "+index+" index");
    }
    this.screens[name] = screen;
  }
  this.getScreen = function(name)
  {
    if(this.screens[name])
      return this.screens[name];
    return null;
  }
  this.setScreen = function(idx)
  {
    if( idx==this.activeScreen)
      return;
    if(!this.screens[idx])
    {
      alert("Game:setScreen(): Warning - have no screen at "+idx+" index!");
      return;
    }
    this.previousScreen = this.activeScreen;
    if( this.screens[this.previousScreen] )
      this.screens[this.previousScreen].onDeactive();
    this.activeScreen = idx;
    //this.screens[this.activeScreen].onActive();
  }
  this.run = function()
  {
    var currTime = (new Date()).getTime()-this.startTime;
    var elapseMls;
    if(this.firstRun)
    {
      elapseMls = 0;
      this.startTime = currTime;
      currTime = 0;
      this.firstRun = false;
    }
    else
      elapseMls = currTime-this.time;
    this.time = currTime;
    var isResourceBlocking = this.resourceManager.onTick(elapseMls);
    if (isResourceBlocking) {
      return;
    }
    var screen = this.screens[ this.activeScreen];
    if (this.activeScreen != this.previousScreen) {
      screen.onActive();
      this.previousScreen = this.activeScreen;
    }
    screen.onTick(elapseMls);
  }
  // Set event handle
  canvas.addEventListener("mousedown",onMouseDown, true);
  canvas.addEventListener("mousemove",onMouseMove, true);
  canvas.addEventListener("mouseup",onMouseUp, true);
  canvas.addEventListener("mousewheel",onMouseWheel,false);
  canvas.addEventListener("DOMMouseScroll", onMouseWheel, false);

  canvas.addEventListener("mouseover",onMouseOver,true);
  canvas.addEventListener("mouseout",onMouseOut,true);  
   
  window.addEventListener("keyup",onKeyUp,true);
  window.addEventListener("keydown",onKeyDown,true);
  window.addEventListener("keypress",onKeyPress, true);
  activeGame = this;
}

function gewScreen(gameObj)
{
  this.scene2d = null;
  this.scene3d = null;
  this.physicsEngine = null;
  this.game = gameObj;
  this.gl   = gameObj.gl;
  this.onTick = function(mls)
  {
    var gl = this.gl;
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    console.log(mls);
  }
  this.onActive = function()
  {
    //console.log("The screen '"+this.game.activeScreen+"' is active");
  }
  this.onDeactive = function()
  {
    //console.log("The screen '"+this.game.activeScreen+"' is deactive");
  }
  this.onMouseUp = function(event)
  {
    //console.log("Screen: Mouse Up Event("+event.canvasX+","+event.canvasY+")");
  }
  this.onMouseDown = function(event)
  {
    //console.log("Screen: Mouse Down Event("+event.canvasX+","+event.canvasY+")");
  }
  this.onMouseMove = function(event)
  {
    //console.log("Screen: Mouse Move Event("+event.canvasX+","+event.canvasY+")");
  }
  this.onMouseWheel = function(event)
  {
    //console.log("Screen: Mouse Wheel Event("+event.canvasX+","+event.canvasY+","+event.delta+")");
  }
  this.onKeyDown = function(event)
  {
    //console.log("Screen: Key Down Event ("+event.keyCode+")");
  }
  this.onKeyUp = function(event)
  {
    //console.log("Screen: Key Up Event ("+event.keyCode+")");
  }
  this.onKeyPress = function(event)
  {
    //console.log("Screen: Key Press Event ("+event.keyCode+")");
  }
}